package com.dragon.pear.modules.sample.common.config;

import com.dragon.common.spring.openapi.ApiGroup;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author Chris Chan
 * Create On 2025/10/1 下午12:41
 * Use for:
 * Explain:
 */
@Slf4j
//@Configuration
public class SampleOpenApiConfig {
    @Bean
    public GroupedOpenApi sample() {
        return GroupedOpenApi.builder()
                .group("sample")
                .displayName("演示")
                .addOperationCustomizer(getOperationCustomizer())
                .addOpenApiCustomizer(getOpenApiCustomizer())
                .build();
    }

    private OpenApiCustomizer getOpenApiCustomizer() {
        return new OpenApiCustomizer() {
            @Override
            public void customise(OpenAPI openApi) {
                log.info("开始过滤路径...");
                Paths paths = new Paths();
                // 用于收集所有被使用的标签
                Set<String> usedTags = new HashSet<>();
                AtomicInteger count = new AtomicInteger();

                openApi.getPaths().forEach((path, pathItem) -> {
                    pathItem.readOperationsMap().forEach((httpMethod, operation) -> {
                        Map<String, Object> extensions = operation.getExtensions();
                        if (extensions != null) {
                            String apiGroup = (String) extensions.get("x-api-group");
                            if (Objects.equals(apiGroup, "sample")) {
                                log.info("✅ 保留路径: {} {}, 分组: {}", httpMethod, path, apiGroup);
                                paths.addPathItem(path, pathItem);
                                count.getAndIncrement();

                                // 收集此操作上定义的标签
                                if (operation.getTags() != null) {
                                    usedTags.addAll(operation.getTags());
                                }
                            }
                        }
                    });
                });

                openApi.setPaths(paths);
                log.info("过滤完成，保留 {} 个路径", count);

                // 2. 清理全局未使用的Tags
                List<Tag> globalTags = openApi.getTags();
                if (globalTags != null) {
                    // 保留那些在usedTags集合中存在的tag
                    List<Tag> cleanedGlobalTags = globalTags.stream()
                            .filter(tag -> tag != null && tag.getName() != null && usedTags.contains(tag.getName()))
                            .collect(Collectors.toList());
                    openApi.setTags(cleanedGlobalTags);
                }
            }
        };
    }

    private OperationCustomizer getOperationCustomizer() {
        return new OperationCustomizer() {
            @Override
            public Operation customize(Operation operation, HandlerMethod handlerMethod) {
                // 直接在匿名类中实现逻辑，避免方法调用问题
                boolean support = SampleOpenApiConfig.this.isSupportDirect(handlerMethod, "sample");
                if (support) {
                    log.info("✅ 标记 - beanType:{}, summary:{}, 线程:{}",
                            handlerMethod.getBeanType().getName(),
                            operation.getSummary(),
                            Thread.currentThread().getName());
                    operation.addExtension("x-api-group", "sample");
                } else {
                    log.info("❌ 跳过 - beanType:{}, summary:{}, 线程:{}",
                            handlerMethod.getBeanType().getName(),
                            operation.getSummary(),
                            Thread.currentThread().getName());
                }
                return operation;
            }
        };
    }

    private boolean isSupportDirect(HandlerMethod handlerMethod, String group) {
        Class<?> beanType = handlerMethod.getBeanType();
        String methodName = handlerMethod.getMethod().getName();

        log.info("🔍 直接判断 - 线程: {}, 类: {}, 方法: {}",
                Thread.currentThread().getName(), beanType.getSimpleName(), methodName);

        String foundGroup = findApiGroupFromClassDirect(beanType);
        boolean result = group.equals(foundGroup);

        log.info("🎯 直接结果 - 类: {}, 期望: {}, 实际: {}, 匹配: {}",
                beanType.getSimpleName(), group, foundGroup, result);

        return result;
    }

    private String findApiGroupFromClassDirect(Class<?> clazz) {
        if (clazz.isAnnotationPresent(ApiGroup.class)) {
            return clazz.getAnnotation(ApiGroup.class).value();
        }

        for (Class<?> interfaceClass : clazz.getInterfaces()) {
            if (interfaceClass.isAnnotationPresent(ApiGroup.class)) {
                return interfaceClass.getAnnotation(ApiGroup.class).value();
            }
        }

        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null && superclass != Object.class) {
            String superGroup = findApiGroupFromClassDirect(superclass);
            if (superGroup != null) {
                return superGroup;
            }
        }

        return null;
    }
}
